<script>
import {
  GlAccordion,
  GlAccordionItem,
  GlSkeletonLoader,
  GlAlert,
  GlFormCheckbox,
  GlButton,
  GlPopover,
  GlSprintf,
  GlLink,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import explainVulnerabilityPromptQuery from 'ee/security_dashboard/graphql/queries/explain_vulnerability_prompt.query.graphql';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import { scrollToElement } from '~/lib/utils/common_utils';

export default {
  components: {
    GlAccordion,
    GlAccordionItem,
    CodeBlock,
    GlSkeletonLoader,
    GlAlert,
    GlFormCheckbox,
    GlButton,
    GlPopover,
    GlSprintf,
    GlLink,
  },
  props: {
    vulnerabilityGraphqlId: { type: String, required: true },
    isDrawerOpen: { type: Boolean, required: true },
  },
  data() {
    return {
      prompts: {},
      loadingError: false,
      promptVisible: false,
      promptLoading: 0,
      checked: false,
      isSecretDetectedWarningDismissed: false,
    };
  },
  apollo: {
    prompts: {
      query: explainVulnerabilityPromptQuery,
      loadingKey: 'promptLoading',
      variables() {
        return { id: this.vulnerabilityGraphqlId };
      },
      update(data) {
        const prompts = data.explainVulnerabilityPrompt;
        this.checked = Boolean(
          prompts.promptWithCode && !prompts.presubmissionChecks.potentialSecretsInCode,
        );
        return prompts;
      },
      error() {
        this.loadingError = true;
      },
    },
  },
  computed: {
    prompt() {
      return this.checked ? this.prompts.promptWithCode : this.prompts.promptWithoutCode;
    },
    accordionText() {
      return this.promptVisible ? this.$options.i18n.hidePrompt : this.$options.i18n.showPrompt;
    },
    isPromptLoading() {
      return this.promptLoading > 0;
    },
    isCheckboxDisabled() {
      return this.isPromptLoading || !this.prompts.promptWithCode || this.isDrawerOpen;
    },
    shouldShowSecretDetectedWarning() {
      return Boolean(
        !this.isSecretDetectedWarningDismissed &&
          this.prompts.presubmissionChecks?.potentialSecretsInCode,
      );
    },
  },
  watch: {
    checked() {
      this.$emit('checkbox-changed', this.checked);
    },
    isPromptLoading() {
      this.$emit('loading-state-changed', this.isPromptLoading);
    },
  },
  methods: {
    scrollToVulnerabilityLocation() {
      scrollToElement('#vulnerability-details-location');
    },
  },
  i18n: {
    showPrompt: s__('Vulnerability|Show prompt'),
    hidePrompt: s__('Vulnerability|Hide prompt'),
    sendCodeWithPrompt: s__('Vulnerability|Send code with prompt'),
    requestError: s__('Vulnerability|Could not load prompt.'),
    popoverTitle: s__('Vulnerability|Sending code to AI'),
    popoverDescription: s__(
      'Vulnerability|Providing the source code improves the response quality. If security is a concern, you can send basic vulnerability info for a generic example.',
    ),
    secretDetectedWarningTitle: s__('Vulnerability|Warning: possible secrets detected'),
    secretDetectedWarning: s__(
      'Vulnerability|GitLab has identified sensitive strings in the code snippet for the AI prompt, indicating a possible leaked secret. Please review your code before utilizing the Explain This Vulnerability feature. If you still wish to proceed and send the %{linkStart}code%{linkEnd} to the AI, click the checkbox below.',
    ),
  },
};
</script>

<template>
  <div>
    <gl-alert
      v-if="shouldShowSecretDetectedWarning"
      :title="$options.i18n.secretDetectedWarningTitle"
      variant="warning"
      class="gl-mb-4 gl-mt-3"
      data-testid="secret-detected-warning"
      @dismiss="isSecretDetectedWarningDismissed = true"
    >
      <gl-sprintf :message="$options.i18n.secretDetectedWarning">
        <template #link="{ content }">
          <gl-link @click="scrollToVulnerabilityLocation">{{ content }}</gl-link>
        </template>
      </gl-sprintf>
    </gl-alert>

    <div class="gl-display-flex">
      <gl-form-checkbox
        v-model="checked"
        :indeterminate="isPromptLoading"
        :disabled="isCheckboxDisabled"
      >
        {{ $options.i18n.sendCodeWithPrompt }}
        <gl-button ref="icon" icon="information-o" variant="link" class="gl-ml-2" />
        <gl-popover
          :target="() => $refs.icon.$el"
          :title="$options.i18n.popoverTitle"
          :delay="0"
          show-close-button
        >
          {{ $options.i18n.popoverDescription }}
        </gl-popover>
      </gl-form-checkbox>
    </div>

    <gl-accordion :header-level="3" class="gl-mb-4">
      <gl-accordion-item v-model="promptVisible" :title="accordionText">
        <code-block
          v-if="isPromptLoading"
          class="gl-px-4 gl-pt-4 gl-pb-3"
          data-testid="loading-block"
        >
          <gl-skeleton-loader />
        </code-block>
        <gl-alert
          v-else-if="loadingError"
          variant="danger"
          :dismissible="false"
          data-testid="loading-error"
        >
          {{ $options.i18n.requestError }}
        </gl-alert>
        <code-block v-else class="gl-px-4 gl-py-3" data-testid="prompt-block">{{
          prompt
        }}</code-block>
      </gl-accordion-item>
    </gl-accordion>
  </div>
</template>
